package com.uuah.server.config.spring.parsers.delegate;

import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;

import com.uuah.server.config.spring.parsers.IUuahDefinitionParser;
import com.uuah.server.config.spring.parsers.IUuahDefinitionParserConfiguration;
import com.uuah.server.config.spring.parsers.PostProcessor;
import com.uuah.server.config.spring.parsers.PreProcessor;
import com.uuah.server.config.spring.parsers.assembly.configuration.IValueMap;

/**
 * This encapsulates several definition parsers, selected depending on the
 * parent element in the DOM.
 */
public class ParentContextDefinitionParser extends
		AbstractParallelDelegatingDefinitionParser {

	private Map parsers = new HashMap();
	private IUuahDefinitionParser otherwise = null;

	public ParentContextDefinitionParser(String context,
			IUuahDefinitionParser parser) {
		and(context, parser);
	}

	public ParentContextDefinitionParser and(String context,
			IUuahDefinitionParser parser) {
		StringTokenizer names = new StringTokenizer(context);
		while (names.hasMoreTokens()) {
			parsers.put(names.nextToken(), parser);
		}
		addDelegate(parser);
		return this;
	}

	public ParentContextDefinitionParser otherwise(IUuahDefinitionParser otherwise) {
		this.otherwise = otherwise;
		return this;
	}

	protected IUuahDefinitionParser getDelegate(Element element,
			ParserContext parserContext) {
		String context = element.getParentNode().getLocalName();
		if (parsers.containsKey(context)) {
			return (IUuahDefinitionParser) parsers.get(context);
		} else if (null != otherwise) {
			return otherwise;
		} else {
			throw new IllegalStateException("No parser defined for "
					+ element.getLocalName() + " in the context " + context);
		}
	}

	protected IUuahDefinitionParser getOtherwise() {
		return otherwise;
	}

	// @Override
	public IUuahDefinitionParserConfiguration addAlias(String alias,
			String propertyName) {
		super.addAlias(alias, propertyName);
		if (otherwise != null) {
			otherwise.addAlias(alias, propertyName);
		}
		return this;
	}

	// @Override
	public IUuahDefinitionParserConfiguration addBeanFlag(String flag) {
		super.addBeanFlag(flag);
		if (otherwise != null) {
			otherwise.addBeanFlag(flag);
		}
		return this;
	}

	// @Override
	public IUuahDefinitionParserConfiguration addCollection(String propertyName) {
		super.addCollection(propertyName);
		if (otherwise != null) {
			otherwise.addCollection(propertyName);
		}
		return this;
	}

	// @Override
	public IUuahDefinitionParserConfiguration addIgnored(String propertyName) {
		super.addIgnored(propertyName);
		if (otherwise != null) {
			otherwise.addIgnored(propertyName);
		}
		return this;
	}

	// @Override
	public IUuahDefinitionParserConfiguration addMapping(String propertyName,
			Map mappings) {
		super.addMapping(propertyName, mappings);
		if (otherwise != null) {
			otherwise.addMapping(propertyName, mappings);
		}
		return this;
	}

	// @Override
	public IUuahDefinitionParserConfiguration addMapping(String propertyName,
			String mappings) {
		super.addMapping(propertyName, mappings);
		if (otherwise != null) {
			otherwise.addMapping(propertyName, mappings);
		}
		return this;
	}

	// @Override
	public IUuahDefinitionParserConfiguration addMapping(String propertyName,
			IValueMap mappings) {
		super.addMapping(propertyName, mappings);
		if (otherwise != null) {
			otherwise.addMapping(propertyName, mappings);
		}
		return this;
	}

	// @Override
	public IUuahDefinitionParserConfiguration addReference(String propertyName) {
		super.addReference(propertyName);
		if (otherwise != null) {
			otherwise.addReference(propertyName);
		}
		return this;
	}

	// @Override
	public IUuahDefinitionParserConfiguration registerPostProcessor(
			PostProcessor postProcessor) {
		super.registerPostProcessor(postProcessor);
		if (otherwise != null) {
			otherwise.registerPostProcessor(postProcessor);
		}
		return this;
	}

	// @Override
	public IUuahDefinitionParserConfiguration registerPreProcessor(
			PreProcessor preProcessor) {
		super.registerPreProcessor(preProcessor);
		if (otherwise != null) {
			otherwise.registerPreProcessor(preProcessor);
		}
		return this;
	}

	// @Override
	public IUuahDefinitionParserConfiguration removeIgnored(String propertyName) {
		super.removeIgnored(propertyName);
		if (otherwise != null) {
			otherwise.removeIgnored(propertyName);
		}
		return this;
	}

	// @Override
	public IUuahDefinitionParserConfiguration setIgnoredDefault(boolean ignoreAll) {
		super.setIgnoredDefault(ignoreAll);
		if (otherwise != null) {
			otherwise.setIgnoredDefault(ignoreAll);
		}
		return this;
	}

}
